package com.matt.foundation.utils;

import com.matt.domain.Leads;
import com.matt.commons.exception.BusinessException;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;

import static com.matt.foundation.model.ErrorCode.DATE_FORMAT_ERROR;

/**
 * 基于Java8的日期工具类。
 *
 * @author Tim.Yao，sunfuchang03@126.com
 * @version 1.1 添加注释，添加日期加上日期数计算方法
 * @since 1.0
 */
public class DateUtil {
    /**
     * 获取某一段日期的开始时间和结束时间。
     *
     * @param currentDay 日期字符串
     * @param separator  日期字符串的分隔符
     * @return 包含开始日期毫秒数和结束日期毫秒的map，开始key为<code>beg</code>，结束key<code>end</code>
     * @throws Exception
     */
    public static final Map<String, Long> getCurrentDayBeginAndEnd(String currentDay, String separator) throws Exception {
        Long beg = null;
        Long end = null;
        Map<String, Long> timeMap = new HashMap<>();
        if (StringUtils.isNotBlank(currentDay) && StringUtils.isNotBlank(separator)) {
            try {
                String[] dates = currentDay.split(separator);
                beg = parseToMills(dates[0] + " 00:00:00:000");
                end = parseToMills(dates[1] + " 23:59:59:999");
                timeMap.put("beg", beg);
                timeMap.put("end", end);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
            return timeMap;
        }
        return null;
    }


    public static final Date getDayBegin(Date today) {
        String day = DateUtil.millisToDateTime(today.getTime(), "yyyy-MM-dd");
        return parseToDate(day + " 00:00:00:000");
    }

    public static final Date getDayEnd(Date today) {
        String day = DateUtil.millisToDateTime(today.getTime(), "yyyy-MM-dd");
        return parseToDate(day + " 23:59:59:999");
    }

    /**
     * 获取某一段日期的开始时间和结束时间。
     *
     * @param currentDay 日期字符串
     * @return 包含开始日期毫秒数和结束日期毫秒的map，开始key为<code>beg</code>，结束key<code>end</code>
     * @throws Exception
     */
    public static final Map<String, Date> getCurrentDayBeginAndEnd(String currentDay) {
        Map<String, Date> timeMap = new HashMap<>();

        try {
            timeMap.put("beg", parseToDateMilis(currentDay + " 00:00:00:000"));
            timeMap.put("end", parseToDateMilis(currentDay + " 23:59:59:999"));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return timeMap;
    }

    /**
     * 获得当天的开始时间
     *
     * @param millis
     * @return
     */
    public static final long startOfDayOfMilli(Long millis) {
        return LocalDateTime
                .of(Instant.ofEpochMilli(millis).atZone(ZoneId.systemDefault()).toLocalDate(), LocalTime.MIDNIGHT)
                .atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    /**
     * 获得当天的结束时间
     *
     * @param millis
     * @return
     */
    public static final long endOfDayOfMilli(Long millis) {
        return LocalDateTime
                .of(Instant.ofEpochMilli(millis).atZone(ZoneId.systemDefault()).toLocalDate(), LocalTime.MAX)
                .atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    /**
     * 将字符串日期格式解析为日期毫秒数。
     *
     * @param formatDate 日期字符串
     * @return 日期毫秒数
     * @throws ParseException
     */
    public static final Long parseToMills(String formatDate) throws ParseException {
        Date dt = parseToDate(formatDate);
        return dt.getTime();
    }

    /**
     * 计算开始日期和结束日期之间相差的月份数。
     *
     * @param bigger
     * @param smaller
     * @return
     * @throws ParseException
     */
    public static final int betweenMonths(String bigger, String smaller) throws ParseException {
        return betweenMonths(parseToDate(bigger), parseToDate(smaller));
    }

    public static final int betweenMonths(Date bigger, Date smaller) {
        if (bigger.compareTo(smaller) < 0)
            return 0;
        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        c1.setTime(bigger);
        c2.setTime(smaller);
        Integer year = c1.get(Calendar.YEAR) - c2.get(Calendar.YEAR);
        int month = c1.get(Calendar.MONTH) - c2.get(Calendar.MONTH);
        int days = c1.get(Calendar.DAY_OF_MONTH) - c2.get(Calendar.DAY_OF_MONTH);
        month += (year * 12);
        return days < 0 ? month - 1 : month;
    }


    /**
     * 计算开始日期和结束日期之间相差的小时数。
     *
     * @param begin 开始日期字符串
     * @param end   结束日期字符串
     * @return 小时数
     * @throws ParseException
     */
    public static final long betweenHour(String begin, String end) throws ParseException {
        long deltaMillis = parseToDateHour(end).getTime() - parseToDateHour(begin).getTime();
        return Duration.ofMillis(deltaMillis).toHours();
    }

    /**
     * 计算开始日期和结束日期之间相差的小时数。
     *
     * @param begin 开始日期毫秒数
     * @param end   结束日期毫秒数
     * @return 小时数
     * @throws ParseException
     */
    public static final long betweenHour(long begin, long end) {
        long deltaMillis = end - begin;
        return Duration.ofMillis(deltaMillis).toHours();
    }

    /**
     * 将完整日期解析为包含年月日时分的日期，不包括秒。
     *
     * @param formatDate 原始完整日期字符串
     * @return 包含年月日时分的日期，秒为0
     * @throws ParseException
     */
    public static final Date parseToDateHour(String formatDate) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            if (formatDate.contains("年") || formatDate.contains("月") || formatDate.contains("日")) {
                sdf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分");
                Date dt = sdf.parse(formatDate);
                return dt;
            }
            if (formatDate.contains("/")) {
                sdf = new SimpleDateFormat("yyyy/MM/dd HH/mm");
                Date dt = sdf.parse(formatDate);
                return dt;
            }
            Date dt = sdf.parse(formatDate);
            return dt;
        } catch (ParseException e) {
            throw new BusinessException(DATE_FORMAT_ERROR, "日期格式错误");
        }
    }

    /**
     * 将字符串日期格式化为日期对象。
     *
     * @param formatDate 字符串日期
     * @return 日期对象
     * @throws ParseException
     */
    public static final Date parseToDateMilis(String formatDate)  {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            if (formatDate.contains("年") || formatDate.contains("月") || formatDate.contains("日")) {
                sdf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
                Date dt = sdf.parse(formatDate);
                return dt;
            }
            if (formatDate.contains("/")) {
                sdf = new SimpleDateFormat("yyyy/MM/dd HH/mm/ss");
                Date dt = sdf.parse(formatDate);
                return dt;
            }
            Date dt = sdf.parse(formatDate);
            return dt;
        } catch (ParseException e) {
            throw new BusinessException(DATE_FORMAT_ERROR, "日期格式错误");
        }
    }

    /**
     * 时间转化为   "XXXX年X月X日x时x分"
     *
     * @param date
     * @return
     */
    public static final String parseDateToString(Date date) {
        String str = "";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
        if (date != null)
            str = sdf.format(date);
        return str;
    }

    /**
     * 将字符串日期格式化为包含年月日的日期，时分秒为0.
     *
     * @param formatDate 字符串日期
     * @return 日期对象
     * @throws ParseException
     */
    public static final Date parseToDate(String formatDate) {

        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            if (formatDate.contains("年") || formatDate.contains("月") || formatDate.contains("日")) {
                sdf = new SimpleDateFormat("yyyy年MM月dd日");
                Date dt = sdf.parse(formatDate);
                return dt;
            }
            if (formatDate.contains("/")) {
                sdf = new SimpleDateFormat("yyyy/MM/dd");
                Date dt = sdf.parse(formatDate);
                return dt;
            }
            Date dt = sdf.parse(formatDate);
            return dt;
        } catch (ParseException e) {
            throw new BusinessException(DATE_FORMAT_ERROR, "日期格式错误");
        }
    }

    public static final Date getEndOfMonth(Date day){
        Calendar c = Calendar.getInstance();
        c.setTime(day);
        c.add(Calendar.MONTH, 0);
        c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));//设置为1号,当前日期既为本月第一天
        c.set(Calendar.HOUR, 23);
        c.set(Calendar.MINUTE, 59);
        c.set(Calendar.SECOND, 59);
        c.set(Calendar.MILLISECOND, 999);
        return c.getTime();
    }

    public static final Date getBeginOfMonth(Date day){
        Calendar c = Calendar.getInstance();
        c.setTime(day);
        c.add(Calendar.MONTH, 0);
        c.set(Calendar.DAY_OF_MONTH, 1);//设置为1号,当前日期既为本月第一天
        c.set(Calendar.HOUR, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        return c.getTime();
    }

    public static final Date getBeginOfMonth(String month){
        Calendar c = Calendar.getInstance();
        month += "-01";
        Date day =  parseToDate(month);
        c.setTime(day);
        c.add(Calendar.MONTH, 0);
        c.set(Calendar.DAY_OF_MONTH, 1);//设置为1号,当前日期既为本月第一天
        c.set(Calendar.HOUR, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        return c.getTime();
    }


    /**
     * 将字符串日期格式化为包含年月日的日期，时分秒为0.
     *
     * @param formatDate 字符串日期
     * @return 日期对象
     * @throws ParseException
     */
    public static final Date parseToHour(String formatDate) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
        if (formatDate.contains("时") || formatDate.contains("分")) {
            sdf = new SimpleDateFormat("HH时mm分");
            Date dt = sdf.parse(formatDate);
            return dt;
        }
        if (formatDate.contains("/")) {
            sdf = new SimpleDateFormat("HH/mm");
            Date dt = sdf.parse(formatDate);
            return dt;
        }
        Date dt = sdf.parse(formatDate);
        return dt;
    }

    public static final Date parseToPattern(String formatDate, String pattern) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(pattern);
            Date dt = sdf.parse(formatDate);
            return dt;
        } catch (ParseException e) {
            throw new BusinessException(DATE_FORMAT_ERROR, "日期格式错误");
        }
    }

    /**
     * 将字符串日期格式化为包含年月日的日期，时分秒为0.
     *
     * @param formatDate 字符串日期
     * @return 日期对象
     * @throws ParseException
     */
    public static final Date parseToHourMillis(String formatDate) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
        if (formatDate.contains("时") || formatDate.contains("分") || formatDate.contains("秒")) {
            sdf = new SimpleDateFormat("HH时mm分ss秒");
            Date dt = sdf.parse(formatDate);
            return dt;
        }
        if (formatDate.contains("/")) {
            sdf = new SimpleDateFormat("HH/mm/ss");
            Date dt = sdf.parse(formatDate);
            return dt;
        }
        Date dt = sdf.parse(formatDate);
        return dt;
    }

    /**
     * 获取某一日期是当月的第几天，从1开始。
     *
     * @param instant 日期毫秒数
     * @return 当月第几天
     */
    public static final int getDayOfMonth(long instant) {
        return Instant.ofEpochMilli(instant).atZone(ZoneId.systemDefault()).getDayOfMonth();
    }

    public static String getBeginOfCurrentMonth(SimpleDateFormat format) {
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MONTH, 0);
        c.set(Calendar.DAY_OF_MONTH, 1);//设置为1号,当前日期既为本月第一天
        String first = format.format(c.getTime());
        return first;
    }

    public static Date getBeginOfCurrentMonth() {
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MONTH, 0);
        c.set(Calendar.DAY_OF_MONTH, 1);//设置为1号,当前日期既为本月第一天
        return c.getTime();
    }

    public static Date getBeginOfCurrentQuarter() {
        Calendar c = Calendar.getInstance();

        // 获取当前月份（0-11，注意：Calendar的月份从0开始）
        int month = c.get(Calendar.MONTH);

        // 计算季度的起始月份（0表示第一季度的1月）
        int quarterStartMonth = (month / 3) * 3; // 例如：3月 → 3/3=1 → 1*3=3 → 对应4月？这里需要调整

        // 修正：因为Calendar的月份是0-11，所以需要重新计算：
        // 例如：3月（即month=2）属于第一季度，起始月份是0（1月）
        // 所以正确的计算方式是：quarterStartMonth = (month / 3) * 3;
        // 例如：
        // 当前月是3月（month=2） → 2/3=0 → 0*3=0 → 1月
        // 当前月是5月（month=4） → 4/3=1 → 1*3=3 → 4月（对应第二季度）

        c.set(Calendar.MONTH, quarterStartMonth); // 设置为季度的起始月份
        c.set(Calendar.DAY_OF_MONTH, 1); // 设置为1号
        // 时间归零
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);

        return c.getTime();
    }

    public static Date getBeginOfCurrentYear() {
        Calendar c = Calendar.getInstance();
        // 设置年份为当前年
        int year = c.get(Calendar.YEAR);
        c.clear(); // 清除所有字段以避免其他时间信息干扰
        c.set(year, Calendar.JANUARY, 1, 0, 0, 0); // 设置时间为当年1月1日0点0分0秒
        return c.getTime();
    }

    public static Date getEndOfCurrentMonth() {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
        return c.getTime();
    }

    public static String getEndOfCurrentMonth(long instant, SimpleDateFormat format) {
        Calendar ca = Calendar.getInstance();
        ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));
        String last = format.format(ca.getTime());
        return last;
    }

    public static final long betweenDays(String begin, String end) throws ParseException {
        long beginTime = parseToMills(begin);
        long endTime = parseToMills(end);
        return countDays(endTime - beginTime);
    }

    public static final long betweenDays(Date begin, Date end) {
        long beginTime = begin.getTime();
        long endTime = end.getTime();
        return countDays(endTime - beginTime);
    }

    public static final long betweetMillis(Date begin, Date end) {
        long beginTime = begin.getTime();
        long endTime = end.getTime();
        return countMillis(endTime - beginTime);
    }

    public static final long countDays(long deltaMillis) {
        return Duration.ofMillis(deltaMillis).toDays();
    }

    public static final long countMillis(long deltaMillis) {
        return Duration.ofMillis(deltaMillis).toMillis();
    }


    public static final long plusMonths(long instant, long months) {
        return Instant.ofEpochMilli(instant).atZone(ZoneId.systemDefault()).plusMonths(months).toInstant().toEpochMilli();
    }

    public static final long plusDays(long instant, long days) {
        return Instant.ofEpochMilli(instant).atZone(ZoneId.systemDefault()).plusDays(days).toInstant().toEpochMilli();
    }

    public static final long minusDays(long instant, long days) {
        return Instant.ofEpochMilli(instant).atZone(ZoneId.systemDefault()).minusDays(days).toInstant().toEpochMilli();
    }

    public static final Long plusDays(String currentDay, long days) {
        try {
            long current = parseToMills(currentDay);
            return plusDays(current, days);
        } catch (ParseException e) {
            throw new BusinessException(DATE_FORMAT_ERROR, "日期格式错误");
        }
    }

    public static final Date plusYear(String currentDay, int year) throws ParseException {
        return new Date(plusDays(currentDay, year * 365));
    }

    public static final String plusDaysToString(String currentDay, long day, String pattern) throws ParseException {
        long millis = plusDays(currentDay, day);
        return millisToDateTime(millis, pattern);
    }

    public static final Date plusDaysToDate(String currentDay, long days) throws ParseException {
        long millis = plusDays(currentDay, days);
        return new Date(millis);
    }

    /**
     * 计算日期加上某天数后的日期。
     *
     * @param currentDay 原始日期
     * @param days       天数
     * @return 计算后的日期
     * @throws ParseException
     */
    public static final Date plusDaysToDate(Date currentDay, long days) {
        long millis = plusDays(currentDay.getTime(), days);
        return new Date(millis);
    }

    /**
     * 日期的毫秒数加上秒数，得到的日期毫秒。
     *
     * @param instant 日期的毫秒数
     * @param seconds 描述
     * @return 计算后的日期毫秒数
     */
    public static final long plusSeconds(long instant, long seconds) {
        return Instant.ofEpochMilli(instant).atZone(ZoneId.systemDefault()).plusSeconds(seconds).toInstant().toEpochMilli();
    }

    /**
     * 日期的毫秒数加上分钟数，得到的日期毫秒。
     *
     * @param instant 日期的毫秒数
     * @param minutes 分钟数
     * @return 计算后的日期毫秒数
     */
    public static final long plusMinutes(long instant, long minutes) {
        return Instant.ofEpochMilli(instant).atZone(ZoneId.systemDefault()).plusMinutes(minutes).toInstant().toEpochMilli();
    }

    /**
     * 计算日期加上某小时数后的日期。
     *
     * @param srcDate 原始日期
     * @param hours   小时数
     * @return 计算后日期
     */
    public static final Date plusHoursToDate(Date srcDate, int hours) {
        long milli = Instant.ofEpochMilli(srcDate.getTime()).atZone(ZoneId.systemDefault()).plusHours(hours).toInstant().toEpochMilli();
        return new Date(milli);
    }

    public static final String millisToDateTime(Long millis, String pattern) {
        LocalDateTime time = Instant.ofEpochMilli(millis).atZone(ZoneId.systemDefault()).toLocalDateTime();
        return time.format(DateTimeFormatter.ofPattern(pattern));
    }

    public static final String getBeginOfTheMouth(long instant) {
        return Instant.ofEpochMilli(instant).atZone(ZoneId.systemDefault()).with(TemporalAdjusters.firstDayOfMonth()).toString();
    }

    public static final boolean isBeforeThanToday(Date day) throws ParseException {
        long now = System.currentTimeMillis();
        return day.getTime() < now;
    }

    /**
     * 判断某一时间是否在一个区间内
     *
     * @param sourceTime 时间区间,半闭合,如[10:00-20:00)
     * @param curTime    需要判断的时间 如10:00
     * @return
     * @throws IllegalArgumentException
     */
    public static boolean isInTime(String sourceTime, String curTime) {
        if (sourceTime == null || !sourceTime.contains("-") || !sourceTime.contains(":")) {
            throw new IllegalArgumentException("Illegal Argument arg:" + sourceTime);
        }
        if (curTime == null || !curTime.contains(":")) {
            throw new IllegalArgumentException("Illegal Argument arg:" + curTime);
        }
        String[] args = sourceTime.split("-");
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
        try {
            long now = sdf.parse(curTime).getTime();
            long start = sdf.parse(args[0]).getTime();
            long end = sdf.parse(args[1]).getTime();
            if (args[1].equals("00:00")) {
                args[1] = "24:00";
            }
            if (end < start) {
                if (now >= end && now < start) {
                    return false;
                } else {
                    return true;
                }
            } else {
                if (now >= start && now < end) {
                    return true;
                } else {
                    return false;
                }
            }
        } catch (ParseException e) {
            e.printStackTrace();
            throw new IllegalArgumentException("Illegal Argument arg:" + sourceTime);
        }
    }


    public static Date getWeekBegin(Date today) {
        Long intervalDay = Long.valueOf(LocalDate.now().getDayOfWeek().getValue() - DayOfWeek.MONDAY.getValue());
        Long millis = LocalDateTime.ofInstant(Instant.ofEpochMilli(today.getTime()), ZoneId.systemDefault()).toLocalDate().minusDays(intervalDay).atStartOfDay().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
        return new Date(millis);
    }

    public static Date getWeekEnd(Date today) {
        Long intervalDay = Long.valueOf(DayOfWeek.SUNDAY.getValue() - LocalDate.now().getDayOfWeek().getValue());
        Long millis = LocalDateTime.ofInstant(Instant.ofEpochMilli(today.getTime()), ZoneId.systemDefault()).toLocalDate().plusDays(intervalDay).atTime(23, 59, 59).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
        return new Date(millis);
    }

    public static boolean hasTimeUnionSet(Date beg1, Date end1, Date beg2, Date end2) {
        if (beg2.compareTo(end1) >= 0 || beg1.compareTo(end2) >= 0)
            return false;
        return true;
    }

    /**
     * 把date类型转为sql date
     *
     * @param date
     * @return
     */
    public static java.sql.Date sqlDate(Date date) {
        if (date != null)
            return new java.sql.Date(date.getTime());
        else
            return null;
    }


    public static String dateToymd(Date date){
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(date);
    }

    public static String dateToymdhhmmss(Date date){
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        return sdf.format(date);
    }

    /**
     * 比较日期 年月日 是否在同一天
     * @param d1
     * @param d2
     * @return
     */
    public static boolean sameDate(Date d1, Date d2){
       return DateUtils.isSameDay(d1, d2);
    }

    /**
     * 比较两个时间 d1>d2
     * @param d1
     * @param d2
     * @return
     */
    public static boolean compareDate(Date d1, Date d2) {
        LocalDate localDate1 = ZonedDateTime.ofInstant(d1.toInstant(), ZoneId.systemDefault()).toLocalDate();
        LocalDate localDate2 = ZonedDateTime.ofInstant(d2.toInstant(), ZoneId.systemDefault()).toLocalDate();
        return localDate1.isAfter((localDate2));
    }


    /**
     * 获取莫个月有多少天。
     *
     * @param month 当前月份 yyyy-MM
     * @return 当月第几天
     */
    public static final int getDaysOfMonth(String month) {
        month += "-01";
        Date day =  parseToDate(month);
        Calendar m = Calendar.getInstance();
        m.setTime(day);
        m.set(Calendar.DATE, 1);//把日期设置为当月第一天
        m.roll(Calendar.DATE, -1);//日期回滚一天，也就是最后一天
        int maxDate = m.get(Calendar.DATE);
        return maxDate;
    }


    public static final Date getEndOfMonth(String month){
        Calendar c = Calendar.getInstance();
        month += "-01";
        Date day =  parseToDate(month);
        c.setTime(day);
        c.add(Calendar.MONTH, 0);
        c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));//设置为1号,当前日期既为本月第一天
        c.set(Calendar.HOUR, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        return c.getTime();
    }


    //获取当前时间上个月最后一天
    public static final Date getEndOfLastMonth(Date day){
        Calendar c = Calendar.getInstance();
        c.setTime(day);
        c.add(Calendar.MONTH, -1);
        c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));//设置为1号,当前日期既为本月第一天
        c.set(Calendar.HOUR, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        return c.getTime();
    }

    /**
     * 获取出生到现在多少天
     *
     * @param date  当前日期
     * @param date1 生日
     * @return
     */
    public static int birthdayDay(Date date, Date date1) {
        long betweenDays = (date.getTime() - date1.getTime()) / (1000L*3600L*24L);
        return (int) Math.abs(betweenDays);
    }

    /**
     * 精确的月份
     *
     * @param bigger
     * @param smaller
     * @return
     */
    public static final double betweenMonthsV2(Date bigger, Date smaller) {
        if (bigger.compareTo(smaller) < 0)
            return 0;
        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        c1.setTime(bigger);
        c2.setTime(smaller);
        Integer year = c1.get(Calendar.YEAR) - c2.get(Calendar.YEAR);
        int month = c1.get(Calendar.MONTH) - c2.get(Calendar.MONTH);
        int days = c1.get(Calendar.DAY_OF_MONTH) - c2.get(Calendar.DAY_OF_MONTH);

        double daysOfMonth = getDayCountOfMonth() * 1.0;

        double monthDelta = days * 1.0 / daysOfMonth;

        double ret = month + (year * 12) + monthDelta;

        return ret;
    }

    private static int getDayCountOfMonth() {
        Calendar aCalendar = Calendar.getInstance(Locale.CHINA);
        int day = aCalendar.getActualMaximum(Calendar.DATE);
        return day;
    }

    /**
     * 添加天数
     * @param date
     * @param day
     * @return  添加后的时间
     */
    public static  Date addDay(Date date ,int day){
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        // 把日期往后增加一天,整数  往后推,负数往前移动
        calendar.add(Calendar.DATE, day);
        // 这个时间就是日期往后推一天的结果
        return  calendar.getTime();
    }

    public static Date isWeekend(Date date,Integer day) throws Exception {
        int count = 1;
        if (day<0){
            count =-1;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
            return  isWeekend(DateUtil.addDay(date, count),day);
        } else {
            return DateUtil.addDay(date, day);
        }
    }

    public static String convertStr(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(date);
    }

    public static String getMonthLast(String date) {
        if (Objects.isNull(date)  || StringUtils.equals("null",date) ){
            return null;
        }
        //设置时间格式
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        //获得实体类
        Calendar ca = Calendar.getInstance();
        ca.setTime(DateUtil.parseToDate(date));
        //设置最后一天
        ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));
        //最后一天格式化
        String lastDay = format.format(ca.getTime());
        return lastDay +" 23:59:59";
    }

    public static void main(String[] args) {
        betweenMonthsV2(new Date(),getEndOfLastMonth(new Date()));
    }
}
